﻿// ========================================================================
//  EveHQ - An Eve-Online™ character assistance application
//  Copyright © 2005-2012  EveHQ Development Team
//  
//  This file (RavenCacheProvider.cs), is part of EveHQ.
// 
//  EveHQ is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 2 of the License, or
//  (at your option) any later version.
// 
//  EveHQ is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with EveHQ.  If not, see <http://www.gnu.org/licenses/>.
// =========================================================================

namespace EveHQ.Caching
{
    using System;
    using System.Threading.Tasks;

    using Raven.Client;
    using Raven.Client.Embedded;

    /// <summary>The raven cache provider.</summary>
    public class RavenCacheProvider : ICacheProvider
    {
        /// <summary>The _db.</summary>
        private readonly EmbeddableDocumentStore _db;

        /// <summary>Initializes a new instance of the <see cref="RavenCacheProvider"/> class.</summary>
        /// <param name="dataFolder">The data folder.</param>
        public RavenCacheProvider(string dataFolder)
        {
            _db = new EmbeddableDocumentStore { DataDirectory=dataFolder };
            _db.Conventions.AllowMultipuleAsyncOperations = true;
            _db.Initialize();
        }

        /// <summary>The add.</summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="cacheUntil">The cache until.</param>
        /// <typeparam name="T"></typeparam>
        public void Add<T>(string key, T value, DateTimeOffset cacheUntil)
        {
            var cacheItem = new TextCacheItem<T> { Data = value, CacheUntil = cacheUntil };
            using (IAsyncDocumentSession session = _db.OpenAsyncSession())
            {
                session.StoreAsync(cacheItem, key).Wait();
                session.SaveChangesAsync().Wait();
            }
        }

        /// <summary>The get.</summary>
        /// <param name="key">The key.</param>
        /// <typeparam name="T"></typeparam>
        /// <returns>The <see cref="T"/>.</returns>
        public T Get<T>(string key)
        {
            T data = default(T);
            using (IAsyncDocumentSession session = _db.OpenAsyncSession())
            {
                Task<TextCacheItem<T>> task = session.LoadAsync<TextCacheItem<T>>(key);
                task.Wait();
                TextCacheItem<T> result = task.Result;
                if (result != null)
                {
                    if (result.CacheUntil < DateTimeOffset.UtcNow)
                    {
                        session.Delete(result);
                    }
                    else
                    {
                        data = result.Data;
                    }
                }
            }
            return data;
        }
    }
}